--[[
Desc: 整形的数学库
Auth: 张宇飞
Date: 2015-09-14    
--]]

-- 0-90度的正弦表。正弦结果均x1000
local deg90sin1000 = {
0, 17, 34, 52, 69, 87, 104, 121, 139, 156, 173, 190, 207, 224, 241, 258, 275, 292, 309, 
325, 342, 358, 374, 390, 406, 422, 438, 453, 469, 484, 499, 515, 529, 544, 559, 573, 587, 
601, 615, 629, 642, 656, 669, 681, 694, 707, 719, 731, 743, 754, 766, 777, 788, 798, 809, 
819, 829, 838, 848, 857, 866, 874, 882, 891, 898, 906, 913, 920, 927, 933, 939, 945, 951, 
956, 961, 965, 970, 974, 978, 981, 984, 987, 990, 992, 994, 996, 997, 998, 999, 999, 1000
};

-- 1-89度正切表。正切结果均x1000
local deg89tan1000 = {
17, 34, 52, 69, 87, 105, 122, 140, 158, 176, 194, 212, 230, 249, 267, 286, 305, 324, 344, 363, 383, 
404, 424, 445, 466, 487, 509, 531, 554, 577, 600, 624, 649, 674, 700, 726, 753, 781, 809, 839, 869, 
900, 932, 965, 999, 1035, 1072, 1110, 1150, 1191, 1234, 1279, 1327, 1376, 1428, 1482, 1539, 1600, 1664, 
1732, 1804, 1880, 1962, 2050, 2144, 2246, 2355, 2475, 2605, 2747, 2904, 3077, 3270, 3487, 3732, 4010,
4331, 4704, 5144, 5671, 6313, 7115, 8144, 9514, 11430, 14300, 19081, 28636, 57289
};

-- 将角度缩放到-180 - 180之间
function normalize180(d)
	if (d >= 360 or d < 0) then
		d = d - math.floor(d / 360) * 360
	end
	if (d > 180) then
		d = d - 360
	end
	return d
end

-- 求sin
function sin1000(deg)
	deg = normalize180(deg);
	if (deg > 90) then
		deg = deg90sin1000[181 - deg];
	elseif (deg >= 0) then
		deg = deg90sin1000[deg + 1];
	elseif (deg < -90) then
		deg = -deg90sin1000[deg + 181];
	else
		deg = -deg90sin1000[-deg + 1];
	end
	return deg;
end

-- 求cos
function cos1000(deg)
	-- 转换成正弦求出结果	
	deg = normalize180(deg);
	if (deg > 90) then
		deg = -deg90sin1000[deg - 89];
	elseif (deg >= 0) then
		deg = deg90sin1000[91 - deg];
	elseif (deg < -90) then
		deg = -deg90sin1000[-89 - deg];
	else
		deg = deg90sin1000[91 + deg];
	end
	return deg;
end

-- 二分查找tan值
function bsearchtan(n, l, r, mint)
	local ll = r - l;
	if (ll < 1) then
		return;
	elseif (1 == ll) then
		mint[2] = mint[3];
		return;
	else
		ll = math.floor(ll / 2 + l);
	end

	local k = deg89tan1000[ll] - n;
	local abk = math.abs(k);
	if ((not mint[1]) or (k < mint[1])) then
		mint[1] = abk
		mint[2] = ll;
	end
	if (abk < 10) then
		return;
	elseif (k > 0) then
		mint[3] = l;
		bsearchtan(n, l, ll, mint);
	else
		mint[3] = r;
		bsearchtan(n, ll, r, mint);
	end
end

-- 求角度
function atandeg(y, x)
	local ret;
	if (0 == y) then
		ret = (x < 0) and 180 or 0;
	elseif (0 == x) then
		ret = (y > 0) and 90 or -90;
	else
		-- 执行2分查找，记录差值最小的位置
		local mint = {};
		bsearchtan(math.abs(math.floor(y * 1000 / x)), 1, #deg89tan1000, mint);
		-- 象限转换
		if (y > 0) then
			ret = (x > 0) and mint[2] or -mint[2];
		else
			ret = -mint[2] - ((x > 0) and 0 or 90);
		end
	end
	return ret;
end
